#include "KimeraII.h"
#include "KimeraStruct.h"

KimeraII::KimeraII(void)
{
	Instrument::Instrument();

	Resolution = 3300000.0f/32768.0f/8500.0f;
	DigitalMax	=	32768;
	DigitalMin	=	0;
	DigitalOffset = 32768/2;
	
	MyName = _("Kimera II");
	Initialize(8,256,20);
	pDev = NULL;
}

KimeraII::~KimeraII(void)
{
	if(pDev != NULL)
	{
		delete pDev;
		pDev = NULL;
	}
}

int KimeraII::GetBatteryLevel(void)
{
	H_KimeraII			Header;
	F_KimeraII			Footer;
	int Dim,read,Level;
	char *Buffer;

	wxLongLong	Begin;
	C_KimeraII Command={0,0,0,0};
	Command.Header = 'o';
	Command.MessageID = K2_CHECKBATTERY;
	if(pDev !=NULL)		pDev->Write((char*)&Command,sizeof(Command));

	Dim = sizeof(Header);
	Buffer = (char*)&Header;
	read = 0;
	Begin = ::wxGetLocalTimeMillis();
	do{
		read += pDev->Read(&Buffer[read],Dim-read);
	}while(read < Dim && (::wxGetLocalTimeMillis()-Begin)<KIMII_TIMEOUT );
	
	if(Header.Header == 5 && Header.MessageID == K2_CHECKBATTERY)
	{
		Dim = sizeof(Footer);
		Buffer = (char*)&Footer;
		read = 0;
		Begin = ::wxGetLocalTimeMillis();
		do{
			read += pDev->Read(&Buffer[read],Dim-read);
		}while(read < Dim && (::wxGetLocalTimeMillis()-Begin)<KIMII_TIMEOUT );

		Level = Header.MessageIndex;		
	}else
	{
		do{
			read = pDev->Read(&Buffer[0],1);
		}while(read > 0);
		Level = -2;	
	}

	return Level;
}



void* KimeraII::Entry(void)
{
	H_KimeraII			Header;
	F_KimeraII			Footer;
	B_DataKimeraII		MessData[32];
	
	SampleStruct	Signal;
	memset(&Signal,0,sizeof(Signal));
	Signal.Data.DataLen	=	Channels;

	unsigned int		ExpectedId		=	0;
	bool		SynchOk = false;
	int			Dim,cr;
	int			read;
	char *Buffer;

	Esci = false;
	while(!Esci)
	{
		Dim = sizeof(Header);
		Buffer = (char*)&Header;
		read = 0;
		if(IsRunning)
		{
			do{
				do{
					cr=pDev->Read(&Buffer[read],Dim-read);
					if(cr>0)
					{
						read += cr;
					}else{Sleep(10);}
				}while(read < Dim && !Esci);
				if(Header.Header == 5 && Header.MessageID == 1)
				{
					if(Header.MessageIndex == ExpectedId)
					{
						ExpectedId++;
						SetConnectionFlag(CONNECTION_OK);
					}else
					{
						ExpectedId	= Header.MessageIndex + 1;
						IncLostPacketCounter();
						SetConnectionFlag(CONNECTION_RECOVERED);
					}
					SynchOk = true;
				}else
				{
					SetConnectionFlag(CONNECTION_LOST);
					IncErrorCounter();
					SynchOk = false;
					memcpy(Buffer,&Buffer[1],sizeof(Header)-1);
					read = sizeof(Header)-1;
				}
			}while(!SynchOk && !Esci);

			Dim = Header.MessageLen;
			
			Buffer = (char*)&MessData;
			read = 0;
			do{
				cr = pDev->Read(&Buffer[read],Dim-read);
				if(cr == 0) Sleep(10);
				read += cr;
			}while(read < Dim && !Esci);
			
			Dim = sizeof(Footer);
			Buffer = (char*)&Footer;
			read = 0;
			do{
				cr = pDev->Read(&Buffer[read],Dim-read);
				if(cr == 0) Sleep(10);
				read +=cr;
			}while(read < Dim && !Esci);

			if((Header.Header+128) == Footer.Foot && Header.MessageIndex == Footer.MessageIndex)
			{
				for(unsigned int i = 0; i < Header.MessageLen/sizeof(B_DataKimeraII); i++)
				{
					for(int u=0;u<8;u++)
					{
						Signal.Data.Signal[u] = ((double)(MessData[i].Data[u]));
					}
					if(!Esci)	PutSample(&Signal);
				}
			}else IncErrorCounter();
		}else Sleep(100);
	}

	StopDevice();
	Sleep(100);
	pDev->Close();
	
	return NULL;
}
void KimeraII::StartDevice(wxString FileName,wxString FilePath,bool File)
{
	Instrument::StartDevice(FileName,FilePath,File);
	C_KimeraII Command={0,0,0,0};
	Command.Header = 'o';
	Command.MessageID = K2_START;
	if(!IsRunning)
	{
		IsRunning	=	true;
		if(pDev !=NULL)		pDev->Write((char*)&Command,sizeof(Command));
	}
}
void KimeraII::StopDevice(void)
{
	C_KimeraII Command={0,0,0,0};
	Command.Header = 'o';
	Command.MessageID = K2_STOP;
	if(IsRunning)
	{
		IsRunning	=	false;
		if(pDev !=NULL)		pDev->Write((char*)&Command,sizeof(Command));
		Instrument::StopDevice();
		//wxMessageBox(wxString::Format(wxT("Errori di trasmissione %d\nPacchetti persi %d"),Info.Errors,Info.LostPackets));
	}
}
int KimeraII::OpenPort(const char *PortName, const char *OpenVal2, const char *OpenVal3)
{
	wxBaud baudrate = wxBAUD_115200;

	if(pDev == NULL)	pDev = new wxSerialPort();
	if(pDev->Open(PortName) < 0)
	{
		return -1;	
	}
	pDev->SetBaudRate(baudrate);
	return 1;
}